package clientApp.gui;

import javax.swing.*;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoManager;

import clientApp.netlogic.MyMessageListener;
import clientApp.netlogic.SocketMessageManager;
import clientApp.textlogic.Actions;
import clientApp.textlogic.TextTransfer;


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;
import java.awt.FlowLayout;

import java.awt.Insets;
import java.awt.Font;
import java.awt.Toolkit;

public class StimUI extends JFrame {
	
	private StimMenu menu;
	private JPanel panelToolBar;
	private EditTextPanel editTextPanel;
	private StandartToolbar standartToolBar;
	private TextToolbar textToolBar;
	private RunToolbar runToolBar;
	private JPanel statusPanel;
	private JLabel statusLabel;
	private TextTransfer textTransfer;	//класс, который обрабатывает копирования текста в System Clipboard
	private Actions textActions;		//класс, который обрабатывает все события кнопок
	private UndoManager undoManager;
	private SocketMessageManager messageManager;
	private boolean loginStatus = false;
	
	
	public StimUI() {
		
		super("Stim");
		setIconImage(Toolkit.getDefaultToolkit().getImage(StimUI.class.getResource("/resources/icons/bug.png")));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		textActions = new Actions();
		textTransfer = new TextTransfer();
		undoManager = new UndoManager();
		messageManager = new SocketMessageManager();
		
		/*
		 * Панель меню
		 */
		menu = new StimMenu();
		setJMenuBar(menu);
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{598, 0};
		gridBagLayout.rowHeights = new int[]{10, 0, 0, 0};
		gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
		gridBagLayout.rowWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE};
		getContentPane().setLayout(gridBagLayout);
		
		//обрабатываем нажати меню "Создать"
		menu.getFileMenuItemCreate().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.setNewWindow(StimUI.this, editTextPanel);
				editTextPanel.setEnabled(true);
				standartToolBar.getCloseButton().setEnabled(true);
				menu.getFileMenuItemClose().setEnabled(true);
				menu.getFileMenuItemSaveAs().setEnabled(true);
			}
		});
		
		//обрабатываем нажатие меню "Сохранить как..."
		menu.getFileMenuItemSaveAs().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.writeFileAs(editTextPanel.getText());
				menu.getFileMenuItemSave().setEnabled(true);
				standartToolBar.getSaveButton().setEnabled(true);
				StimUI.this.setTitle(textActions.getFileName());
			}
		});
		
		//обрабатываем нажатие меню "Сохранить"
		menu.getFileMenuItemSave().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.writeFile(editTextPanel.getText());
				StimUI.this.setTitle(textActions.getFileName());
			}
		});
		
		//обрабатываем нажатие меню "Закрыть"
		menu.getFileMenuItemClose().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.closeWindow(StimUI.this, editTextPanel, menu.getFileMenuItemSave(), 
						menu.getFileMenuItemSaveAs(), standartToolBar.getSaveButton());
				standartToolBar.getCloseButton().setEnabled(false);
				menu.getFileMenuItemClose().setEnabled(false);
			}
		});
		
		//обрабатываем нажатие меню "Выход"
		menu.getFileMenuItemExit().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				System.exit(0);
			}
		});
		
		//обрабатывааем нажатие меню "Вырезать"
		menu.getEditMenuItemCut().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String copyText = "";
				copyText = editTextPanel.getSelectedText();
				editTextPanel.replaceSelection("");
				textTransfer.setClipboardContents(copyText);
			}
		});

		//обрабатываем нажатие меню "Копировать"
		menu.getEditMenuItemCopy().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String copyText = "";
				copyText = editTextPanel.getSelectedText();
				textTransfer.setClipboardContents(copyText);
			}
		});

		//обрабатываем нажатие меню "Вставить"
		menu.getEditMenuItemPaste().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String pasteText = "";
				pasteText = textTransfer.getClipboardContents();
				editTextPanel.append(pasteText);
			}
		});

		
		//обрабатываем нажати меню "Выделить все"
		menu.getEditMenuItemSelectAll().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				editTextPanel.selectAll();
			}
		});
		
		//обработка нажатия меню "Отменить"
		menu.getEditMenuItemUndo().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.setUndo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		//обработка нажатия меню "Вернуть"
		menu.getEditMenuItemRedo().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.setRedo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		/*
		 * Панель инструментов
		 */
		panelToolBar = new JPanel();
		panelToolBar.setLayout(new FlowLayout(FlowLayout.LEFT));
		GridBagConstraints gbc_panelToolBar = new GridBagConstraints();
		gbc_panelToolBar.insets = new Insets(0, 0, 5, 0);
		gbc_panelToolBar.anchor = GridBagConstraints.NORTH;
		gbc_panelToolBar.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelToolBar.gridx = 0;
		gbc_panelToolBar.gridy = 0;
		getContentPane().add(panelToolBar, gbc_panelToolBar);
		
		/*
		 * Standart панель
		 */
		standartToolBar = new StandartToolbar();
		panelToolBar.add(standartToolBar);
		
		//обрабатываем нажатие кнопки "Создать"
		standartToolBar.getCreateButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.setNewWindow(StimUI.this, editTextPanel);
				editTextPanel.setEnabled(true);
				standartToolBar.getCloseButton().setEnabled(true);
				menu.getFileMenuItemClose().setEnabled(true);
				menu.getFileMenuItemSaveAs().setEnabled(true);
			}
		});
		//добавляем hotkey для кнопки "Создать"
		standartToolBar.getCreateButton().getActionMap().put("Create", new AbstractAction("Create") {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.setNewWindow(StimUI.this, editTextPanel);
				editTextPanel.setEnabled(true);
				standartToolBar.getCloseButton().setEnabled(true);
				menu.getFileMenuItemClose().setEnabled(true);
				menu.getFileMenuItemSaveAs().setEnabled(true);
			}
		});
		standartToolBar.getCreateButton().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "Create");
		
		
		//обрабатываем нажатие кнопки "Вырезать"
		standartToolBar.getCutButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String copyText = "";
				copyText = editTextPanel.getSelectedText();
				editTextPanel.replaceSelection("");
				textTransfer.setClipboardContents(copyText);
			}
		});

		//обрабатываем нажатие кнопки "Копировать"
		standartToolBar.getCopyButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String copyText = "";
				copyText = editTextPanel.getSelectedText();
				textTransfer.setClipboardContents(copyText);
			}
		});
		
		//обрабатываем нажатие кнопки "Вставить"
		standartToolBar.getPasteButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				String pasteText = "";
				pasteText = textTransfer.getClipboardContents();
				editTextPanel.append(pasteText);
			}
		});
		
		//обрабатываем нажатие кнопки "Отменить"
		standartToolBar.getUndoButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.setUndo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		//обрабатываем нажатие кнопки "Вернуть"
		standartToolBar.getRedoButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.setRedo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		//обрабатываем нажатие кнопки "Открыть"
		standartToolBar.getOpenButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				editTextPanel.setEnabled(true);
				editTextPanel.setText(textActions.openDialog());
				if (textActions.getFileName() != ""){
					StimUI.this.setTitle("Stim - "+textActions.getFileName());
				}
				else 
					StimUI.this.setTitle("Stim - Нове повiдомлення");
			}
		});

		//обрабатываем нажатие кнопки "Сохранить"
		standartToolBar.getSaveButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.writeFile(editTextPanel.getText());
				StimUI.this.setTitle(textActions.getFileName());
			}
		});
		
		//обрабатываем нажатие кнопки "Закрыть"
		standartToolBar.getCloseButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				textActions.closeWindow(StimUI.this, editTextPanel, menu.getFileMenuItemSave(), 
						menu.getFileMenuItemSaveAs(), standartToolBar.getSaveButton());
				standartToolBar.getCloseButton().setEnabled(true);
				menu.getFileMenuItemClose().setEnabled(true);
			}
		});
		
		/*
		 * TextEdit панель
		 */
		textToolBar = new TextToolbar();
		panelToolBar.add(textToolBar);
		
		//обрабатываем изменение размера шрифта
		textToolBar.getFontSizeComboBox().addItemListener(new ItemListener() {
			
			@Override
			public void itemStateChanged(ItemEvent evt) {
				// TODO Auto-generated method stub
				if (evt.getStateChange() == ItemEvent.SELECTED){
					editTextPanel.setFont(new Font("Arial", Font.PLAIN, textToolBar.getFontSize()));
				}
			}
		});
		
		//обрабатываем нажатие кнопки "Bold"
		textToolBar.getBoldButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent evt) {
				// TODO Auto-generated method stub
				if (textToolBar.getBoldButton().isSelected()){
					editTextPanel.setFont(new Font("Arial", Font.BOLD, textToolBar.getFontSize()));
				}
				else {
					editTextPanel.setFont(new Font("Arial", Font.PLAIN, textToolBar.getFontSize()));
				}
			}
		});
		
		/*
		 * Run панель
		 */
		runToolBar = new RunToolbar();
		panelToolBar.add(runToolBar);
		
		//открыть диалог LogIn
		runToolBar.getConnectDBButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				LogInDialog login = new LogInDialog(StimUI.this, "Вхiд у систему", true, messageManager);
				login.setLocationRelativeTo(StimUI.this);
				login.setVisible(true);
				StimUI.this.setFocusable(false);
				loginStatus = login.isStatusLoging();
				if (loginStatus){
					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							statusLabel.setText("Connected");
							runToolBar.getDisconnectDBButton().setEnabled(true);
							runToolBar.getEditMailButton().setEnabled(true);
							runToolBar.getSendMailButton().setEnabled(true);
							runToolBar.getConnectDBButton().setEnabled(false);
						}
					});
				}
				else JOptionPane.showMessageDialog(null, "Неправильнi данi логiну чи паролю", "Помилка входу в систему", JOptionPane.ERROR_MESSAGE);
			}
		});
		
		//отсоеденится от сервера
		runToolBar.getDisconnectDBButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				messageManager.closeConnection();
				loginStatus = false;
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						statusLabel.setText("Disconnected");
						runToolBar.getDisconnectDBButton().setEnabled(false);
						runToolBar.getEditMailButton().setEnabled(false);
						runToolBar.getSendMailButton().setEnabled(false);
						runToolBar.getConnectDBButton().setEnabled(true);
					}
				});
			}
		});
		
		//отправить сообщение
		runToolBar.getSendMailButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				messageManager.sendData(editTextPanel.getText());
			}
		});
		
		/*
		 * Панель ввода текста
		 */
		editTextPanel = new EditTextPanel();
		editTextPanel.setEnabled(false);
		JScrollPane scroller = new JScrollPane(editTextPanel);
		GridBagConstraints gbc_editTextPanel = new GridBagConstraints();
		gbc_editTextPanel.insets = new Insets(0, 0, 5, 0);
		gbc_editTextPanel.fill = GridBagConstraints.BOTH;
		gbc_editTextPanel.gridx = 0;
		gbc_editTextPanel.gridy = 1;
		getContentPane().add(scroller, gbc_editTextPanel);
		
		//слушатель события undo/redo
		editTextPanel.getDocument().addUndoableEditListener(new UndoableEditListener() {
			
			@Override
			public void undoableEditHappened(UndoableEditEvent evt) {
				// TODO Auto-generated method stub
				undoManager.addEdit(evt.getEdit());
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		//обрабатываем нажатие кнопки контекстного меню "Отменить"
		editTextPanel.getUndoButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.setUndo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		//обрабатываем нажатие кнопки контекстного меню "Вернуть"
		editTextPanel.getRedoButton().addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				textActions.setRedo(undoManager);
				textActions.updateUndoRedoButtons(undoManager, standartToolBar.getUndoButton(), standartToolBar.getRedoButton());
				textActions.updateUndoRedoButtons(undoManager, menu.getEditMenuItemUndo(), menu.getEditMenuItemRedo());
				textActions.updateUndoRedoButtons(undoManager, editTextPanel.getUndoButton(), editTextPanel.getRedoButton());
			}
		});
		
		/*
		 * панель состояния
		 */
		statusPanel = new JPanel();
		GridBagConstraints gbc_statusPanel = new GridBagConstraints();
		gbc_statusPanel.fill = GridBagConstraints.HORIZONTAL;
		gbc_statusPanel.gridx = 0;
		gbc_statusPanel.gridy = 2;
		getContentPane().add(statusPanel, gbc_statusPanel);
		statusPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		
		statusLabel = new JLabel("Disconnected from DB");
		statusLabel.setFont(new Font("Arial", Font.PLAIN, 12));
		statusPanel.add(statusLabel);
		
		/*
		 * Внешний вид программы
		 */
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch (Exception exp){
			exp.printStackTrace();
		}
		
		
		
		setSize(600,400);
		setVisible(true);
		
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt){
				if (loginStatus){
					messageManager.closeConnection();
					System.exit(0);
				}
				else System.exit(0);
			}
		});
		
	}
	
}
